#include "g729_interface.h"
#include <string.h>
#ifndef WEBRTC_MAC
#include <malloc.h>
#endif

#include "bcg729/decoder.h"
#include "bcg729/encoder.h"


typedef void *cod_state;
typedef void *dec_state;

void WebRtcG729_Version( char *versionStr, short len )
{
	strncpy(versionStr, "1.1.0\n", len);
}

int16_t WebRtcG729_CreateEnc( G729_encinst_t** inst )
{
	*inst=(G729_encinst_t*)initBcg729EncoderChannel();

	if(*inst!=NULL)
		return 0;

	return -1;
}

int16_t WebRtcG729_CreateDec( G729_decinst_t** inst )
{
	*inst=(G729_decinst_t*)initBcg729DecoderChannel();

	if(*inst!=NULL)
		return 0;

	return -1;
}

int16_t WebRtcG729_FreeEnc( G729_encinst_t* inst )
{
	closeBcg729EncoderChannel((bcg729EncoderChannelContextStruct *)inst);
	return 0;
}

int16_t WebRtcG729_FreeDec( G729_decinst_t* inst )
{
	closeBcg729DecoderChannel((bcg729DecoderChannelContextStruct *)inst);
	return 0;
}

int16_t WebRtcG729_Encode( G729_encinst_t* encInst, int16_t* input, int16_t len, int16_t* output )
{
	int out_len = 0;
        int i;
	for (i = 0; i < len; i += 80)
	{
		bcg729Encoder((bcg729EncoderChannelContextStruct *)encInst, input + i, ((uint8_t*)output) + out_len);
		out_len += 10;
	}
	
	return out_len;
}

int16_t WebRtcG729_EncoderInit( G729_encinst_t* encInst, int16_t mode )
{
	return 0;
}


#define L_PACKED_G729A 10
int16_t WebRtcG729_Decode( G729_decinst_t *dec_inst, const int16_t *encoded, int16_t len, int16_t *decoded, int16_t *speechType )
{
    int bad_frame = 0;
    
    if(len < L_PACKED_G729A){
        bad_frame = 1;
        *speechType = 2;
		bcg729Decoder((bcg729DecoderChannelContextStruct *)dec_inst, (unsigned char*)encoded, bad_frame, (int16_t *)decoded);
		return 80;
    }else{
        *speechType = 1;
    }

	int out_frame_samples = 0;
	int bits_stream_cnt = len / L_PACKED_G729A;
    	int i;
	for (i= 0; i < bits_stream_cnt; i++ )
	{
		bcg729Decoder((bcg729DecoderChannelContextStruct *)dec_inst,
			((unsigned char*)encoded) + (i * L_PACKED_G729A),
			0,
			((int16_t *)decoded) + (i * 80));

		out_frame_samples += 80;
	}

	return out_frame_samples;
}

int16_t WebRtcG729_DecodeBwe( G729_decinst_t* decInst, int16_t* input )
{
	return 0;
}

int16_t WebRtcG729_DecodePlc( G729_decinst_t* decInst )
{
	return 0;
}

int16_t WebRtcG729_DecoderInit( G729_decinst_t* decInst )
{
	return 0;
}

